﻿using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.NetworkAnalyst;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Display;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using MapFormsApp.Models;
using MapFormsApp.Helpers;

namespace MapFormsApp.Services
{
    public class RoutingService : IDisposable
    {
        private readonly INetworkDataset _networkDataset;
        private INAContext _naContext;
        private bool _isDisposed;

        public RoutingService(INetworkDataset networkDataset)
        {
            _networkDataset = networkDataset ?? throw new ArgumentNullException(nameof(networkDataset));
            InitializeNAContext();
        }

        private void InitializeNAContext()
        {
            //INASolver naSolver = new NAClass();
            //_naContext = naSolver.CreateContext(_networkDataset, "RouteAnalysis");

            //INASolverParameters solverParams = _naContext.SolverParameters;
            //solverParams.ImpedanceAttributeName = "WalkTime";
            //solverParams.RestrictionAttributeNames = "Oneway";
            //solverParams.FindBestOrder = false;
        }

        public RouteResult CalculateRoute(IPoint startPoint, IPoint endPoint)
        {
            ValidatePoints(startPoint, endPoint);

            try
            {
                // 添加起止点
                INALocation startStop = CreateStop(startPoint, "起点");
                INALocation endStop = CreateStop(endPoint, "终点");
                IList<INALocation> stops = new List<INALocation> { startStop, endStop };
                // 执行路径分析
                INASolver naSolver = _naContext.Solver;
                // 创建必要的辅助对象
                IGPMessages messages = new GPMessagesClass();
                ITrackCancel trackCancel = new CancelTrackerClass();

                // 调用正确的Solve方法
                bool success = naSolver.Solve(_naContext, messages, trackCancel);

                // 解析结果
                return ParseRouteResult();
            }
            catch (COMException ex)
            {
                throw new RoutingException("路径计算失败", ex.ErrorCode);
            }
        }

        private RouteResult ParseRouteResult()
        {
            INAResult naResult = _naContext.Result;

            // 验证结果有效性
            if (naResult == null || !naResult.HasValidResult)
            {
                return new RouteResult
                {
                    IsSuccess = false,
                    ErrorMessage = "未找到有效路径"
                };
            }

            // 获取输出属性集
            IPropertySet outputProps = naResult.OutputProperties;

            // 创建路径结果对象
            return new RouteResult
            {
                IsSuccess = true,
                PathGeometry = ExtractPathGeometry(outputProps),
                TotalDistance = GetPropertyValue<double>(outputProps, "Total_Length"),
                TotalTime = GetPropertyValue<double>(outputProps, "Total_WalkTime") / 60 // 转换为分钟
            };
        }

        private IPolyline ExtractPathGeometry(IPropertySet outputProps)
        {
            if (outputProps == null) return null;

            try
            {
                // 使用 GetProperty 方法获取几何对象
                object geometryObj = outputProps.GetProperty("Output_Geometry");
                return geometryObj as IPolyline;
            }
            catch
            {
                return null;
            }
        }

        private T GetPropertyValue<T>(IPropertySet props, string key)
        {
            if (props == null) return default(T);

            try
            {
                // 使用 GetProperty 方法获取属性值
                object value = props.GetProperty(key);
                if (value is T)
                {
                    return (T)value;
                }
                return default(T);
            }
            catch
            {
                return default(T);
            }
        }

        private INALocation CreateStop(IPoint point, string name)
        {
            // 创建位置对象
            INALocation location = new NALocationClass();
            // 设置位置属性（通过扩展方法）
            //location.SourcePosition = point;
            //location.SetAsRequiredStop();

            return location;
        }

        private void ValidatePoints(IPoint start, IPoint end)
        {
            if (start == null || end == null)
                throw new ArgumentNullException("起止点不能为空");

            if (((IGeometry)start).SpatialReference.FactoryCode !=
                ((IGeometry)end).SpatialReference.FactoryCode)
                throw new RoutingException("起止点坐标系不一致");
        }

        public void Dispose()
        {
            if (_isDisposed) return;

            if (_naContext != null)
            {
                Marshal.ReleaseComObject(_naContext);
                _naContext = null;
            }
            _isDisposed = true;
            GC.SuppressFinalize(this);
        }

        ~RoutingService() => Dispose();
    }

    public class RoutingException : Exception
    {
        public int ErrorCode { get; }

        public RoutingException(string message, int errorCode = -1)
            : base(message) => ErrorCode = errorCode;
    }
}